#include "at32f415_spi_driver.h"
#include "string.h"
__IO uint8_t dma_buf[5];


__IO uint8_t spi1_tx_buffer[BUFFERSIZE];
    #if SPI_DMA_MODE
    #else
__IO uint8_t spi1_cmd_buffer[BUFFERSIZE];
    #endif

__IO uint16_t tx_index=0;
__IO uint16_t pu_index=0;
__IO uint32_t send_ov_flag = 1;
__IO uint32_t buffer_num = 0;
__IO uint32_t buffer_status[2] = {0,0};
void app_spi_dma_init()
{
    dma_init_type dma_init_struct;

    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    dma_reset(DMA1_CHANNEL1);
    dmamux_enable(DMA1, TRUE);
    dmamux_init(DMA1MUX_CHANNEL1, DMAMUX_DMAREQ_ID_SPI1_TX);

    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = 1;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = FALSE;

    dma_init_struct.memory_base_addr = (uint32_t)spi1_tx_buffer;
    dma_init_struct.peripheral_base_addr = (uint32_t)&(SPI1->dt);
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    dma_init(DMA1_CHANNEL1, &dma_init_struct);
}
void app_spi_init(void)
{
	//--------------
	spi_init_type spi_init_struct;
	gpio_init_type gpio_initstructure;
    
    #if SPI_DMA_MODE
    app_spi_dma_init();
    #endif
	//--------------
	crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
	gpio_default_para_init(&gpio_initstructure);
    #if SPI_CS_HDMODE
	/* spi1 cs pin */
	gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
	gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
	gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
	gpio_initstructure.gpio_pins           = GPIO_PINS_4;
	gpio_init(GPIOA, &gpio_initstructure);
    gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE4, GPIO_MUX_5);
    #endif
	/* spi1 sck pin */
	gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
	gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_initstructure.gpio_pull           = GPIO_PULL_DOWN;
	gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
	gpio_initstructure.gpio_pins           = GPIO_PINS_5;
	gpio_init(GPIOA, &gpio_initstructure);
    gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_5);
	/*spi1 miso pin */
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
	gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
	gpio_initstructure.gpio_pins           = GPIO_PINS_6;
	gpio_init(GPIOA, &gpio_initstructure);
    gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_5);
	/* spi1 mosi pin */
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
	gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
	gpio_initstructure.gpio_pins           = GPIO_PINS_7;
	gpio_init(GPIOA, &gpio_initstructure);
    gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_5);

	//---------------
	crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);

	spi_default_para_init(&spi_init_struct);
    #if SPI_HALF_MODE
	spi_init_struct.transmission_mode = SPI_TRANSMIT_HALF_DUPLEX_TX;
    #else
    spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
    #endif
	spi_init_struct.master_slave_mode =SPI_MODE_MASTER;
	spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_4; //72MHZ 
	spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
	spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
	spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_LOW;
	spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
    #if SPI_CS_HDMODE
	spi_init_struct.cs_mode_selection = SPI_CS_HARDWARE_MODE;
    spi_hardware_cs_output_enable(SPI1,TRUE);
    #else
    spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
    #endif
	spi_init(SPI1, &spi_init_struct);
    
    #if SPI_IRQ_MODE
    nvic_irq_enable(SPI1_IRQn, 0, 0);
    #endif
    
    #if SPI_DMA_MODE
    nvic_irq_enable(DMA1_Channel1_IRQn,0,0);
    spi_i2s_dma_transmitter_enable(SPI1,TRUE);
    dma_interrupt_enable(DMA1_CHANNEL1,DMA_FDT_INT,TRUE);
    dma_interrupt_enable(DMA1_CHANNEL1,DMA_HDT_INT,TRUE);
    //while(dma_flag_get(DMA1_FDT1_FLAG) == RESET);
    #endif
    
    spi_enable(SPI1, TRUE);


}

void spi_send_byte(uint8_t data)
{
    #if 1
    while(spi_i2s_flag_get(SPI1, SPI_I2S_TDBE_FLAG) == RESET)
    {};
    spi_i2s_data_transmit(SPI1, data);
        
	while (spi_i2s_flag_get(SPI1,SPI_I2S_RDBF_FLAG) == RESET)
	{}; 
	spi_i2s_data_receive(SPI1);
    #else

    #endif
        

}

void spi_irq_send_start()
{
    tx_index = 0;
    send_ov_flag = 0;
    spi_i2s_interrupt_enable(SPI1, SPI_I2S_TDBE_INT, TRUE);
}
void wait_dma_stop()
{
    while(buffer_status[buffer_num] == 1);
}
void spi_dma_send_start()
{
    while(buffer_status[buffer_num] == 1);
    dma_channel_enable(DMA1_CHANNEL1, FALSE);
    #if DMA_ONE_BUFF
    DMA1_CHANNEL1->maddr = (uint32_t)spi1_tx_buffer;
    buffer_status[buffer_num] = 1;
    #else
    buffer_num=(buffer_num+1)%2;
    buffer_status[buffer_num] = 1;
    if(buffer_num==1)
    {
        DMA1_CHANNEL1->maddr = (uint32_t)spi1_tx_buffer;
    }else
    {
        DMA1_CHANNEL1->maddr = (uint32_t)(spi1_tx_buffer+BUFFERSIZE/2);
    }
    #endif
    dma_data_number_set(DMA1_CHANNEL1, pu_index);
    dma_channel_enable(DMA1_CHANNEL1, TRUE);
    pu_index = 0;
}
void TFT_WR_Byte_3(u8 dat)
{
    #if DMA_ONE_BUFF
    *(spi1_tx_buffer+pu_index) = dat;
    #else
    uint32_t index;
    index = buffer_num?(BUFFERSIZE/2):0;
    if(pu_index == 0)
    {
        memset((void *)(spi1_tx_buffer+index),0,BUFFERSIZE/2);
    }
    *(spi1_tx_buffer+pu_index+index) = dat;
    #endif
    #if SPI_DMA_MODE
    #else
    spi1_cmd_buffer[pu_index] = 1;
    #endif
    pu_index++;
    if(pu_index == BUFFERSIZE/2)
    {
        spi_dma_send_start();
    }

}
extern AT32F415GPIO spi_cs;
extern AT32F415GPIO spi_dc;
void SPI1_IRQHandler(void)
{
    if(spi_i2s_flag_get(SPI1, SPI_I2S_TDBE_FLAG) != RESET)
    {
        if(send_ov_flag == 0)
        {
            #if SPI_DMA_MODE
            #else
            if(spi1_cmd_buffer[tx_index])
            {
              spi_dc.set(&spi_dc); 
            }else
            {
              spi_dc.clr(&spi_dc);
            }
            #endif
            #if SPI_CS_HDMODE
            #else
            spi_cs.clr(&spi_cs);
            #endif
            spi_i2s_data_transmit(SPI1, spi1_tx_buffer[tx_index++]);
            
            if(tx_index == pu_index)
            {
                spi_i2s_interrupt_enable(SPI1, SPI_I2S_TDBE_INT, FALSE);
                send_ov_flag = 1;
                pu_index = 0;
            }
        }
    }
    if(spi_i2s_flag_get(SPI1, SPI_I2S_RDBF_FLAG) != RESET)
    {
        spi_i2s_data_receive(SPI1);
        #if SPI_CS_HDMODE
        #else
        spi_cs.set(&spi_cs);
        #endif
        #if SPI_DMA_MODE
        #else
        spi_dc.set(&spi_dc); 
        #endif
    }
}

void DMA1_Channel1_IRQHandler()
{
    if(dma_flag_get(DMA1_FDT1_FLAG) != RESET)
    {
        dma_flag_clear(DMA1_FDT1_FLAG);
        buffer_status[buffer_num] = 0;
        send_ov_flag = 1;
        //pu_index = 0;
    }
    if(dma_flag_get(DMA1_HDT1_FLAG) != RESET)
    {
        dma_flag_clear(DMA1_HDT1_FLAG);
        send_ov_flag = 1;
        //pu_index = 0;
    }
    
}